<template>
  <view class="number-box">
    <view
      class="number-box__minus"
      :style="{
        width: `${buttonSize}rpx`,
        height: `${buttonSize}rpx`,
      }"
    >
      <image
        v-show="!isDisabled('minus')"
        :src="`${img_baseUrl}/statics/std/static/new/minus_green.png`"
        @click="clickHandler('minus')"
      />
      <image v-show="isDisabled('minus')" :src="`${img_baseUrl}/statics/std/static/new/minus_gray.png`" />
    </view>
    <view
      class="number-box__value"
      :style="{
        height: `${buttonSize}rpx`,
      }"
      :class="{ 'number-box__input--disabled': disabled }"
    >
      {{ currentValue }}
    </view>
    <view
      class="number-box__plus"
      :style="{
        width: `${buttonSize}rpx`,
        height: `${buttonSize}rpx`,
      }"
    >
      <image
        v-show="!isDisabled('plus')"
        :src="`${img_baseUrl}/statics/std/static/new/add_green.png`"
        @click="clickHandler('plus')"
      />
      <image v-show="isDisabled('plus')" :src="`${img_baseUrl}/statics/std/static/new/add_gray.png`" />
    </view>
  </view>
</template>
<script>
export default {
  props: {
    // 用于双向绑定的值，初始化时设置设为默认min值(最小值)
    value: {
      type: [String, Number],
      default: 1,
    },
    // 最小值
    min: {
      type: [String, Number],
      default: 1,
    },
    // 最大值
    max: {
      type: [String, Number],
      default: Number.MAX_SAFE_INTEGER,
    },
    // 是否禁用，包括输入框，加减按钮
    disabled: {
      type: Boolean,
      default: false,
    },
    // 按钮大小，宽高等于此值，单位rpx，输入框高度和此值保持一致
    buttonSize: {
      type: Number,
      default: 48,
    },
  },
  data() {
    return {
		img_baseUrl: process.env.VUE_APP_BASEURL_IMG_API,
      // 输入框实际操作的值
      currentValue: "",
      step: 1,
    };
  },
  computed: {
    // 用于监听多个值发生变化
    watchChange() {
      return [this.min, this.max];
    },
    isDisabled() {
      return (type) => {
        if (type === "plus") {
          // 在点击增加按钮情况下，判断整体的disabled，是否单独禁用增加按钮，以及当前值是否大于最大的允许值
          return this.disabled || this.currentValue >= this.max;
        }
        if (type === "minus") {
          // 点击减少按钮同理
          return this.disabled || this.currentValue <= this.min;
        }
      };
    },
  },
  watch: {
    // 多个值之间，只要一个值发生变化，都要重新检查check()函数
    watchChange() {
      this.check();
    },
    // 监听v-mode的变化，重新初始化内部的值
    value(n) {
      if (n !== this.currentValue) {
        this.currentValue = this.format(this.value);
      }
    },
  },
  mounted() {
    this.init();
  },
  methods: {
    init() {
      this.currentValue = this.format(this.value);
    },
    // 过滤非法的字符
    filter(value) {
      // 只允许0-9之间的数字，"."为小数点，"-"为负数时候使用
      value = String(value).replace(/[^0-9.-]/g, "");
      return value;
    },
    // 格式化整理数据，限制范围
    format(value) {
      value = this.filter(value);
      // 如果为空字符串，那么设置为0，同时将值转为Number类型
      value = value === "" ? 0 : +value;
      // 对比最大最小值，取在min和max之间的值
      value = Math.max(Math.min(this.max, value), this.min);
      return value;
    },
    check() {
      // 格式化了之后，如果前后的值不相等，那么设置为格式化后的值
      const val = this.format(this.currentValue);
      if (val !== this.currentValue) {
        this.currentValue = val;
      }
    },
    // 点击加减按钮
    clickHandler(type) {
      this.type = type;
      this.onChange();
    },
    // 对值扩大后进行四舍五入，再除以扩大因子，避免出现浮点数操作的精度问题
    add(num1, num2) {
      const cardinal = Math.pow(10, 10);
      return Math.round((num1 + num2) * cardinal) / cardinal;
    },
    onChange() {
      const { type } = this;
      const diff = type === "minus" ? -this.step : +this.step;
      const value = this.format(this.add(+this.currentValue, diff));
      this.emitChange(value);
      this.$emit(type);
    },
    // 发出change事件
    emitChange(value) {
      this.$emit("input", value);
      this.currentValue = value;
    },
  },
};
</script>

<style lang="scss" scoped>
.number-box {
  display: flex;

  .number-box__minus,
  .number-box__plus {
    display: flex;

    image {
      width: 100%;
      height: 100%;
    }
  }

  .number-box__value {
    width: 72rpx;
    margin: 0 4rpx;
    font-size: 32rpx;
    font-weight: 500;
    color: rgba(0, 0, 0, 0.7);
    line-height: 44rpx;
    display: flex;
    justify-content: center;
    align-items: center;

    &.number-box__input--disabled {
      opacity: 0.5;
    }
  }
}
</style>
